import axios, { AxiosInstance, AxiosPromise, AxiosRequestConfig, AxiosResponse, InternalAxiosRequestConfig } from 'axios';
import qs from 'qs';

interface AxiosConfig {
	withCredentials?: boolean;
	baseURL?: string;
	timeout: number;
}

export interface HttpResult<R> {
	code: string;
	message: string;
	result: R;
}

const axiosConfig: AxiosConfig = {
	withCredentials: true,
	timeout: 6000
};

interface CustomAxiosRequestConfig extends AxiosRequestConfig {
	custom?: boolean;
}

const POST_FORM_OPTION = {
	transformRequest: [
		function (data: any) {
			return qs.stringify(data);
		}
	],
	headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
};

class Request {
	instance: AxiosInstance;
	constructor(config: AxiosConfig) {
		this.instance = axios.create(config);
		this.interceptors(this.instance);
	}

	private interceptors(instance: AxiosInstance) {
		instance.interceptors.request.use(
			(config: InternalAxiosRequestConfig) => {
				// 添加Authorization
				return config;
			},
			(error) => {
				console.log('axios request error', error);
				return Promise.reject(error);
			}
		);
		instance.interceptors.response.use(
			(response: AxiosResponse) => {
				const { data, config }: { data: HttpResult<any>; config: CustomAxiosRequestConfig } = response;
				const { code, result } = data;
				const custom = config.custom;

				if (code === '1') {
					return result;
				} else {
					const message = data.message;
					if (!custom) {
						// 全局错误提示
					}
				}
			},
			(error) => {
				return Promise.reject(error);
			}
		);
	}

	/**
	 * ajax get
	 * @param url
	 * @param params
	 * @param {boolean} custom 是否自定义错误消息 默认false
	 * @returns
	 */
	public get<T>(url: string, params?: object, custom: boolean = false): Promise<T> {
		return this.instance.get(url, {
			params,
			custom
		} as CustomAxiosRequestConfig);
	}

	public post<T>(url: string, params?: object, isFormData?: boolean): Promise<T> {
		let options = isFormData ? POST_FORM_OPTION : {};
		return this.instance.post(url, params, options);
	}
}

export default new Request(axiosConfig);
